package com.meng.ioc_demo;

import android.content.ComponentName;
import android.content.Intent;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.meng.baselibrary.app.ExceptionCrashHandlerApp;
import com.meng.hotfix.HotFix;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by Administrator on 2017/5/4.
 */

public class App extends ExceptionCrashHandlerApp{
    private static final String TAG ="APP_TAG";
    @Override
    public void onCreate() {
        super.onCreate();
        HotFix.getInstance().init(this);
        HotFix.getInstance().injectHack("hack.dex");
        String patchPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/0/ioc.patch";
        if(new File(patchPath).exists()){
            HotFix.getInstance().injectSdcardFile(patchPath);
            Toast.makeText(this, "补丁已打好啦", Toast.LENGTH_SHORT).show();
        }
        try {
            hookStartActivity();
            hookLaunchActivity();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * hook startActivity方法
     * @throws Exception
     */
    public void hookStartActivity() throws Exception{
        // 先获取ActivityManagerNative中的gDefault
        Class<?> amnClazz = Class.forName("android.app.ActivityManagerNative");
        Field defaultField = amnClazz.getDeclaredField("gDefault");
        defaultField.setAccessible(true);
        Object gDefaultObj = defaultField.get(null);

        // 获取Singleton里面的mInstance
        Class<?> singletonClazz = Class.forName("android.util.Singleton");
        Field amsField = singletonClazz.getDeclaredField("mInstance");
        amsField.setAccessible(true);
        //获取IActivityManager对象
        Object amsObj = amsField.get(gDefaultObj);

        // 动态代理Hook下钩子
        amsObj = Proxy.newProxyInstance(getClass().getClassLoader(),
                amsObj.getClass().getInterfaces(),
                new StartActivityInvocationHandler(amsObj));
        // 注入
        amsField.set(gDefaultObj,amsObj);
    }

    /**
     * Start Activity Invocation Handler
     */
    private class StartActivityInvocationHandler implements InvocationHandler {
        private Object mAmsObj;
        public StartActivityInvocationHandler(Object amsObj){
            this.mAmsObj = amsObj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 拦截到所有ActivityManagerService的方法
            Log.e(TAG,"methodName:"+method.getName());
            if(method.getName().equals("startActivity")){
                // 启动Activity的方法,找到原来的Intent
                Intent realIntent = (Intent) args[2];
                // 代理的Intent
                Intent proxyIntent = new Intent();
                proxyIntent.setComponent(new ComponentName(getApplicationContext(),ProxyActivity.class));
//                // 把原来的Intent绑在代理Intent上面
                proxyIntent.putExtra("realIntent",realIntent);
//                // 让proxyIntent去晒太阳，借尸
                args[2] = proxyIntent;
                Log.e(TAG, "realIntent:" + realIntent);
            }
            Object obj = null;
            try{
                obj = method.invoke(mAmsObj,args);
            }catch (Exception e){
            }
            return obj;
        }
    }

    /**
     * hook Launch Activity
     */
    public void hookLaunchActivity() throws Exception{
        // 获取ActivityThread
        Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread");
        Field sCurrentActivityThreadField = activityThreadClazz.getDeclaredField("sCurrentActivityThread");
        sCurrentActivityThreadField.setAccessible(true);
        Object sCurrentActivityThreadObj = sCurrentActivityThreadField.get(null);
        // 获取Handler mH
        Field mHField = activityThreadClazz.getDeclaredField("mH");
        mHField.setAccessible(true);
        Handler mH = (Handler) mHField.get(sCurrentActivityThreadObj);
        // 设置Callback
        Field callBackField = Handler.class.getDeclaredField("mCallback");
        callBackField.setAccessible(true);
        callBackField.set(mH, new ActivityThreadHandlerCallBack());
    }
    class ActivityThreadHandlerCallBack implements Handler.Callback {

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == 100) {
                handleLaunchActivity(msg);
            }
            return false;
        }
    }
    // 还魂
    private void handleLaunchActivity(Message msg) {
        // final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
        try {
            Object obj = msg.obj;
            Field intentField = obj.getClass().getDeclaredField("intent");
            intentField.setAccessible(true);
            Intent proxyIntent = (Intent) intentField.get(obj);
            // 代理意图
            Intent originIntent = proxyIntent.getParcelableExtra("realIntent");
            if (originIntent != null) {
                // 替换意图
                intentField.set(obj, originIntent);
                Log.d(TAG, "替换意图");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
